/**    
 * @Description: 博客园地址：https://www.cnblogs.com/zumengjie/      
 * @author: 顶风少年   
 * @date: 2021年4月4日 下午6:20:21
 */

package datang.dtdb.datasource.pooled;

import java.io.PrintWriter;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.sql.Connection;
import java.sql.SQLException;
import java.sql.SQLFeatureNotSupportedException;
import java.util.LinkedList;
import java.util.logging.Logger;

import javax.sql.DataSource;

import datang.dtdb.datasource.unpooled.UnpooledDataSource;
import datang.dtdb.exceptions.DataSourceException;

/**
 * 一个简单的连接池，仅仅初始化了指定容量的连接，close不会关闭
 */
public class PooledDataSource implements DataSource {

	/**
	 * 使用UnpooledDataSource获取连接
	 */
	public UnpooledDataSource dataSource;

	/**
	 * 连接池
	 */
	private LinkedList<Connection> pool = new LinkedList<>();

	/**
	 * 默认 核心连接数
	 */
	private Integer DEFAULTCORECTIONSIZE = 10;

	/**
	 * 用户设置的核心连接数
	 **/

	private Integer coreSize;

	/**
	 * 创建UnpooledDataSource
	 */
	public PooledDataSource() {
		dataSource = new UnpooledDataSource();
	}

	/**
	 * 设置核心线程
	 */
	public void setCoreSize(Integer coreSize) {
		this.coreSize = coreSize;
	}

	/**
	 * 初始化连接池
	 */
	public void initPool() {
		if (coreSize == null) {
			for (int i = 0; i < DEFAULTCORECTIONSIZE; i++) {
				pool.add(getProxyConnection());
			}
		} else {
			for (int i = 0; i < coreSize; i++) {
				pool.add(getProxyConnection());
			}
		}
	}

	/**
	 * 从连接池获取连接
	 */
	@Override
	public Connection getConnection() {
		synchronized (this) {
			if (pool.size() > 0) {
				return pool.removeFirst();
			} else {
				throw new DataSourceException("暂时没有连接可以用");
			}
		}
	}

	/**
	 * 创建代理连接
	 */
	public Connection getProxyConnection() {
		/**
		 * 创建连接
		 */
		Connection connection = dataSource.getConnection();
		/**
		 * 生成代理对象
		 */
		return (Connection) Proxy.newProxyInstance(this.getClass().getClassLoader(),
				connection.getClass().getInterfaces(), new InvocationHandler() {
					public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
						/**
						 * 如果是关闭，则添加到池中
						 */
						if (method.getName().equals("close")) {
							pool.add(connection);
							return null;
						} else {
							return method.invoke(connection, args);
						}
					}
				});
	}

	@Override
	public PrintWriter getLogWriter() throws SQLException {
		return null;
	}

	@Override
	public void setLogWriter(PrintWriter out) throws SQLException {
	}

	@Override
	public void setLoginTimeout(int seconds) throws SQLException {
	}

	@Override
	public int getLoginTimeout() throws SQLException {
		return 0;
	}

	@Override
	public Logger getParentLogger() throws SQLFeatureNotSupportedException {
		return null;
	}

	@Override
	public <T> T unwrap(Class<T> iface) throws SQLException {
		return null;
	}

	@Override
	public boolean isWrapperFor(Class<?> iface) throws SQLException {
		return false;
	}

	@Override
	public Connection getConnection(String username, String password) throws SQLException {
		return null;
	}

}
